from rest_framework import viewsets, permissions, status
from rest_framework.decorators import action
from rest_framework.response import Response
from django_filters import rest_framework as filters
from django.utils import timezone
from datetime import timedelta
from django.db import models
from .models import Book
from .serializers import BookSerializer, BookListSerializer

class BookFilter(filters.FilterSet):
    title = filters.CharFilter(lookup_expr='icontains')
    author = filters.CharFilter(lookup_expr='icontains')
    isbn = filters.CharFilter(lookup_expr='icontains')
    publisher = filters.CharFilter(lookup_expr='icontains')
    category_id = filters.NumberFilter(field_name='category')
    status = filters.ChoiceFilter(choices=Book.STATUS_CHOICES)
    available = filters.BooleanFilter(method='filter_available')

    class Meta:
        model = Book
        fields = ['title', 'author', 'isbn', 'publisher', 'category_id', 'status', 'available']

    def filter_available(self, queryset, name, value):
        if value:
            return queryset.filter(status='available')
        return queryset

class BookViewSet(viewsets.ModelViewSet):
    """
    图书视图集
    """
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = [permissions.IsAuthenticated]
    filterset_class = BookFilter
    search_fields = ['title', 'author', 'isbn', 'publisher', 'description']

    def get_serializer_class(self):
        """根据操作返回不同的序列化器"""
        if self.action == 'list':
            return BookListSerializer
        return BookSerializer

    @action(detail=True, methods=['post'])
    def borrow(self, request, pk=None):
        """
        借阅图书
        """
        book = self.get_object()

        # 检查图书是否可借阅
        if not book.is_available():
            return Response(
                {'error': '该图书当前不可借阅'}, 
                status=status.HTTP_400_BAD_REQUEST
            )

        # 创建借阅记录
        due_date = timezone.now() + timedelta(days=30)  # 默认借阅30天
        borrowing = Borrowing.objects.create(
            book=book,
            borrower=request.user,
            due_date=due_date,
            status='active'
        )

        # 更新图书状态
        book.status = 'borrowed'
        book.save()

        serializer = BorrowingSerializer(borrowing)
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    @action(detail=True, methods=['post'])
    def return_book(self, request, pk=None):
        """
        归还图书
        """
        book = self.get_object()
        current_borrowing = book.get_current_borrowing()

        if not current_borrowing:
            return Response(
                {'error': '该图书没有被借出'}, 
                status=status.HTTP_400_BAD_REQUEST
            )

        # 检查借阅者是否为当前用户或管理员
        if current_borrowing.borrower != request.user and not request.user.is_staff:
            return Response(
                {'error': '您没有权限归还此图书'}, 
                status=status.HTTP_403_FORBIDDEN
            )

        # 更新借阅记录
        current_borrowing.return_date = timezone.now()

        # 检查是否逾期
        if current_borrowing.is_overdue():
            current_borrowing.status = 'overdue'
        else:
            current_borrowing.status = 'returned'

        current_borrowing.save()

        # 更新图书状态
        book.status = 'available'
        book.save()

        serializer = BorrowingSerializer(current_borrowing)
        return Response(serializer.data)

    @action(detail=False, methods=['get'])
    def search(self, request):
        """
        搜索图书
        """
        query = request.query_params.get('q', '')
        if not query:
            return Response({'error': '请提供搜索关键词'}, status=status.HTTP_400_BAD_REQUEST)

        # 在标题、作者、ISBN和描述中搜索
        books = self.queryset.filter(
            models.Q(title__icontains=query) |
            models.Q(author__icontains=query) |
            models.Q(isbn__icontains=query) |
            models.Q(description__icontains=query)
        )

        serializer = self.get_serializer(books, many=True)
        return Response(serializer.data)

